package entity;

import java.io.Serializable;
import java.util.ArrayList;

/**
 * This is the Row class.  
 */
public class Row extends Movable implements Serializable {
	private static final long serialVersionUID = 1673272816430727300L;
	private static int nextId = 0;
	
	private int id;
	public ArrayList<Word> words;
	public int offsetX;

	/**
	 * Constructor of Row. A row is composed of words in an ArrayList.
	 */
	public Row(int id, ArrayList<Word> words) {
		this.id = id;
		this.words = words;
		this.offsetX = 0;
	}

	/**
	 * Constructor of Row. A row is composed of two words.
	 */
	public Row(int id, Word w1, Word w2) {
		this.id = id;
		this.words = new ArrayList<Word>();
		this.words.add(w1);
		this.words.add(w2);
		this.offsetX = 0;
	}

	/**
	 * Constructor of Row. A row is composed of one word.
	 */
	public Row(int id, Word word) {
		this.id = id;
		this.words = new ArrayList<Word>();
		this.words.add(word);
		this.offsetX = 0;
	}

	/**
	 * Constructor of Row. A row is composed of another row.
	 */
	public Row(Row row) {
		this.words = new ArrayList<Word>();
		this.id = row.getId();
		
		for (Word w : row.getWords()) {
			this.words.add(new Word(w));
		}
		
		this.offsetX = row.getOffsetX();
	}
	
	/**
	 * Get a cope of a row. 
	 */
	public Row clone(){
		return new Row(this);
	}
	
	/**
	 * Add a word to a row. 
	 * You can add the word to the right or the left of the row. 
	 */
	public void addWord(Word word, Edge e) {
		if (e == Edge.RIGHT) {
			words.add(word);
		} else if (e == Edge.LEFT) {
			words.add(0, word);
		}
	}


	/**
	 * Remove a word from a row.
	 */
	public void removeWord(Word word) {
		this.words.remove(word);
	}

	/**
	 * Add a row to another row. 
	 * You can add the row to the right or the left of another row.
	 */
	public void addRow(Row row, Edge e) {
		if (e == Edge.RIGHT) {
			this.words.addAll(row.getWords());
		} else if (e == Edge.LEFT) {
			this.words.addAll(0, row.getWords());
		}
	}
	
	/**
	 * Set position for every word in the row.
	 */
	public void setPosition(int x, int y) {
		int nextWordX = x;
		
		for (Word w : words) {
			w.setPosition(nextWordX, y);
			nextWordX += w.getWidth() + 2;
		}
	}
	
	/**
	 * Reset position for the row.
	 */
	public void rearrange() {
		setPosition(getX(), getY());
	}
	
	/**
	 * Check whether a word in a row.
	 */
	public boolean contains(Word w) {
		return words.contains(w);
	}
	
	/**
	 * Get the position of X direction of the first word in a row.
	 */
	public int getX() {
		return words.get(0).getX();
	}
	
	/**
	 * Get the position of Y direction of the first word in a row.
	 */
	public int getY() {
		return words.get(0).getY();
	}
	
	/**
	 * Update position for a row.
	 */
	public void updatePosition(int x, int y) {
		this.setOffsetX(x);
	}
	
	/**
	 * Check whether a word overlaps a row.
	 */
	public boolean checkCollision(Word w) {
		for(Word w2 : words) {
			if(w.checkCollision(w2)) {
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * Return the string value of every word in a row.
	 */
	public String toString() {
		return words.toString();
	}
	
	/**
	 * Return words in an row.
	 */
	public ArrayList<Word> getWords() {
		return words;
	}

	/**
	 * Return the position of a row.
	 */
	public int getOffsetX() {
		return offsetX;
	}
	
	/**
	 * Set the position of a row.
	 */
	public void setOffsetX(int x) {
		this.offsetX = x;
	}

	/**
	 * Return the position of the first word in a row.
	 */
	public int getAbsoluteX() {
		return words.get(0).getX();
	}

	/**
	 * Return the height of a row.
	 */
	public int getHeight() {
		return words.get(0).getHeight();
	}

	/**
	 * Return the width of a row.
	 */
	public int getWidth() {
		Word firstWord = words.get(0);
		Word lastWord = words.get(words.size() - 1);
		
		int totalWidth = (lastWord.getX() + lastWord.getWidth()) - firstWord.getX();
		
		return totalWidth;
	}
	
	/**
	 * Check whether a row is equals to another word, in terms of not only value, but also all other attributes. 
	 */
	@Override
	public boolean equals(Object o) {
		return o instanceof Row && id == ((Row) o).getId();
	}

	/**
	 * Return the ID of a row.
	 */
	public int getId() {
		return id;
	}

	/**
	 * Set ID for a row.
	 */
	public void setId(int id) {
		this.id = id;
	}
	
	public static int nextId(){
		return nextId++;
	}
}
